﻿// Copyright © Naked Objects Group Ltd ( http://www.nakedobjects.net). 
// All Rights Reserved. This code released under the terms of the 
// Microsoft Public License (MS-PL) ( http://opensource.org/licenses/ms-pl.html) 

using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using NakedObjects;
using NakedObjects.Security;

namespace RestfulObjects.Test.Data {
    public abstract class WithAction {
        public IDomainObjectContainer Container { set; protected get; }

        //public virtual WithReference AAAWithReference() {
        //    return Container.Instances<WithReference>().Single(x => x.Id == 1);
        //}

        //public virtual VerySimpleEager AAAVerySimpleEager() {
        //    return Container.Instances<VerySimpleEager>().Single(x => x.Id == 1);
        //}

        public virtual MostSimple AnAction() {
            return Container.Instances<MostSimple>().Single(x => x.Id == 1);
        }

        public virtual MostSimpleViewModel AnActionReturnsViewModel() {
            var vm = Container.NewViewModel<MostSimpleViewModel>();
            vm.Id = 1;
            return vm;
        }

        public virtual RedirectedObject AnActionReturnsRedirectedObject() {
            return Container.Instances<RedirectedObject>().Single(x => x.Id == 1);
        }

        [QueryOnly]
        public virtual WithDateTimeKey AnActionReturnsWithDateTimeKey() {
            return Container.Instances<WithDateTimeKey>().FirstOrDefault();
        }

        //[QueryOnly]
        //public virtual WithAction AnActionReturnWithAction() {
        //    return Container.Instances<WithAction>().FirstOrDefault();
        //}

        //[QueryOnly]
        //public virtual WithCollection AnActionReturnWithCollection() {
        //    return Container.Instances<WithCollection>().FirstOrDefault();
        //}

        //[QueryOnly]
        //public virtual WithReference AnActionReturnWithReference() {
        //    return Container.Instances<WithReference>().FirstOrDefault();
        //}

        //[QueryOnly]
        //public virtual WithScalars AnActionReturnWithScalars() {
        //    return Container.Instances<WithScalars>().FirstOrDefault();
        //}

        //[QueryOnly]
        //public virtual WithValue AnActionReturnWithValue() {
        //    return Container.Instances<WithValue>().FirstOrDefault();
        //}

        [AuthorizeAction(Users = "ViewUser")]
        public virtual MostSimple AUserDisabledAction() {
            return Container.Instances<MostSimple>().Single(x => x.Id == 1);
        }

        public virtual MostSimple AnActionReturnsNull() {
            return null;
        }

        public virtual MostSimpleViewModel AnActionReturnsNullViewModel() {
            return null;
        }


        public virtual MostSimple AnActionWithOptionalParm([Optionally, Named("Optional Parm"), DescribedAs("an optional parm"), System.ComponentModel.DataAnnotations.MaxLength(101), RegEx(Validation = @"[A-Z]")] string parm) {
            return Container.Instances<MostSimple>().Single(x => x.Id == 1);
        }

        [QueryOnly]
        public virtual MostSimple AnActionWithOptionalParmQueryOnly([Optionally] string parm) {
            return Container.Instances<MostSimple>().Single(x => x.Id == 1);
        }

        [QueryOnly]
        public virtual MostSimple AnActionAnnotatedQueryOnly() {
            return Container.Instances<MostSimple>().Single(x => x.Id == 1);
        }

        [QueryOnly]
        public virtual MostSimpleViewModel AnActionAnnotatedQueryOnlyReturnsViewModel() {
            return AnActionReturnsViewModel();
        }

        [QueryOnly]
        public virtual MostSimple AnActionAnnotatedQueryOnlyReturnsNull() {
            return null;
        }

        [Idempotent]
        public virtual MostSimple AnActionAnnotatedIdempotent() {
            return Container.Instances<MostSimple>().Single(x => x.Id == 1);
        }

        [Idempotent]
        public virtual MostSimpleViewModel AnActionAnnotatedIdempotentReturnsViewModel() {
            return AnActionReturnsViewModel();
        }

        [Idempotent]
        public virtual MostSimple AnActionAnnotatedIdempotentReturnsNull() {
            return null;
        }

        [Hidden]
        public virtual MostSimple AHiddenAction() {
            return Container.Instances<MostSimple>().Single(x => x.Id == 1);
        }

        [Disabled]
        public virtual MostSimple ADisabledAction() {
            return Container.Instances<MostSimple>().Single(x => x.Id == 1);
        }

        [Disabled]
        public virtual IQueryable<MostSimple> ADisabledQueryAction() {
            return Container.Instances<MostSimple>().Where(x => x.Id == 1);
        }

        [Disabled]
        public virtual ICollection<MostSimple> ADisabledCollectionAction() {
            return Container.Instances<MostSimple>().Where(x => x.Id == 1).ToList();
        }

        public virtual int AnActionReturnsScalar() {
            return 999;
        }

        public virtual string AnActionReturnsScalarEmpty() {
            return "";
        }

        public virtual string AnActionReturnsScalarNull() {
            return null;
        }


        public virtual void AnActionReturnsVoid() {}

        public virtual IQueryable<MostSimple> AnActionReturnsQueryable() {
            return Container.Instances<MostSimple>().Where(ms => ms.Id == 1 || ms.Id == 2);
        }

        public virtual ICollection<MostSimple> AnActionReturnsCollection() {
            return Container.Instances<MostSimple>().Where(ms => ms.Id == 1 || ms.Id == 2).ToList();
        }

        public virtual ICollection<MostSimple> AnActionReturnsCollectionEmpty() {
            return new List<MostSimple>();
        }

        public virtual ICollection<MostSimple> AnActionReturnsCollectionNull() {
            return null;
        }

        public virtual void AnActionWithDateTimeParm(DateTime parm) {}

        public virtual IQueryable<MostSimple> AnActionReturnsQueryableWithScalarParameters(int parm1, string parm2) {
            Assert.AreEqual(100, parm1);
            Assert.AreEqual("fred", parm2);
            return Container.Instances<MostSimple>().Where(ms => ms.Id == 1 || ms.Id == 2);
        }

        public virtual ICollection<MostSimple> AnActionReturnsCollectionWithScalarParameters(int parm1, string parm2) {
            Assert.AreEqual(100, parm1);
            Assert.AreEqual("fred", parm2);
            return Container.Instances<MostSimple>().Where(ms => ms.Id == 1 || ms.Id == 2).ToList();
        }

        public virtual IQueryable<MostSimple> AnActionReturnsQueryableWithParameters(int parm1, MostSimple parm2) {
            Assert.AreEqual(101, parm1);
            Assert.AreEqual(Container.Instances<MostSimple>().First(), parm2);
            return Container.Instances<MostSimple>().Where(ms => ms.Id == 1 || ms.Id == 2);
        }

        public virtual ICollection<MostSimple> AnActionReturnsCollectionWithParameters(int parm1, MostSimple parm2) {
            Assert.AreEqual(101, parm1);
            Assert.AreEqual(Container.Instances<MostSimple>().First(), parm2);
            return Container.Instances<MostSimple>().Where(ms => ms.Id == 1 || ms.Id == 2).ToList();
        }

        public virtual int AnActionReturnsScalarWithParameters(int parm1, MostSimple parm2) {
            Assert.AreEqual(101, parm1);
            Assert.AreEqual(Container.Instances<MostSimple>().First(), parm2);
            return 555;
        }

        [DescribedAs("an action for testing")]
        [MemberOrder(Sequence = "1")]
        public virtual void AnActionReturnsVoidWithParameters(int parm1, MostSimple parm2) {
            Assert.AreEqual(101, parm1);
            Assert.AreEqual(Container.Instances<MostSimple>().First(), parm2);
        }

        public virtual MostSimple AnActionReturnsObjectWithParameters(int parm1, MostSimple parm2) {
            Assert.AreEqual(101, parm1);
            Assert.AreEqual(Container.Instances<MostSimple>().First(), parm2);
            return Container.Instances<MostSimple>().First();
        }

        [QueryOnly]
        public virtual MostSimple AnActionReturnsObjectWithParametersAnnotatedQueryOnly(int parm1, MostSimple parm2) {
            Assert.AreEqual(101, parm1);
            Assert.AreEqual(Container.Instances<MostSimple>().First(), parm2);
            return Container.Instances<MostSimple>().First();
        }

        [QueryOnly]
        public virtual MostSimple AnActionReturnsObjectWithParameterAnnotatedQueryOnly(int parm1) {
            Assert.AreEqual(101, parm1);
            return Container.Instances<MostSimple>().First();
        }

        [Idempotent]
        public virtual MostSimple AnActionReturnsObjectWithParametersAnnotatedIdempotent(int parm1, MostSimple parm2) {
            Assert.AreEqual(101, parm1);
            Assert.AreEqual(Container.Instances<MostSimple>().First(), parm2);
            return Container.Instances<MostSimple>().First();
        }

        public virtual MostSimple AnActionWithValueParameter(int parm1) {
            return Container.Instances<MostSimple>().Single(x => x.Id == parm1);
        }

        public virtual MostSimple AnActionWithValueParameterWithChoices(int parm3) {
            return Container.Instances<MostSimple>().Single(x => x.Id == parm3);
        }

        public virtual MostSimple AnActionWithValueParameterWithDefault(int parm5) {
            return Container.Instances<MostSimple>().Single(x => x.Id == parm5);
        }

        public virtual IList<int> Choices0AnActionWithValueParameterWithChoices() {
            return new[] {1, 2, 3};
        }

        public virtual int Default0AnActionWithValueParameterWithDefault() {
            return 4;
        }

        public virtual MostSimple AnActionWithReferenceParameter(MostSimple parm2) {
            return Container.Instances<MostSimple>().Single(x => x.Id == parm2.Id);
        }

        public virtual MostSimple AnActionWithReferenceParameterWithChoices(MostSimple parm4) {
            return Container.Instances<MostSimple>().Single(x => x.Id == parm4.Id);
        }

        public virtual MostSimple AnActionWithReferenceParameterWithDefault(MostSimple parm6) {
            return Container.Instances<MostSimple>().Single(x => x.Id == parm6.Id);
        }

        public virtual IList<MostSimple> Choices0AnActionWithReferenceParameterWithChoices() {
            return Container.Instances<MostSimple>().Where(ms => ms.Id == 1 || ms.Id == 2).ToList();
        }

        public virtual MostSimple Default0AnActionWithReferenceParameterWithDefault() {
            return Container.Instances<MostSimple>().First();
        }

        public virtual MostSimple AnActionWithParametersWithChoicesWithDefaults(int parm1, int parm7, MostSimple parm2, MostSimple parm8) {
            return Container.Instances<MostSimple>().First();
        }

        public virtual IList<int> Choices1AnActionWithParametersWithChoicesWithDefaults() {
            return new[] {1, 2, 3};
        }

        public virtual int Default1AnActionWithParametersWithChoicesWithDefaults() {
            return 4;
        }

        public virtual IList<MostSimple> Choices3AnActionWithParametersWithChoicesWithDefaults() {
            return Container.Instances<MostSimple>().Where(ms => ms.Id == 1 || ms.Id == 2).ToList();
        }

        public virtual MostSimple Default3AnActionWithParametersWithChoicesWithDefaults() {
            return Container.Instances<MostSimple>().First();
        }

        public virtual int AnError() {
            throw new DomainException("An error exception");
        }

        public virtual IQueryable<MostSimple> AnErrorQuery() {
            throw new DomainException("An error exception");
        }

        public virtual ICollection<MostSimple> AnErrorCollection() {
            throw new DomainException("An error exception");
        }

        public virtual int AnActionValidateParameters(int parm1, int parm2) {
            return parm1 + parm2;
        }

        public virtual string ValidateAnActionValidateParameters(int parm1) {
            if (parm1 == 0) {
                return "Fail validation parm1";
            }
            return null;
        }

        public virtual string ValidateAnActionValidateParameters(int parm1, int parm2) {
            if (parm1 > parm2) {
                return "Cross validation failed";
            }
            return null;
        }



        //[QueryOnly]
        //public MostSimpleViewModel AnActionReturnsViewModel() {
        //    var vm = Container.NewViewModel<MostSimpleViewModel>();
        //    vm.AMostSimple = Container.Instances<MostSimple>().First();
        //    vm.AVerySimple = Container.Instances<VerySimple>().First();
        //    return vm; 
        //}

    }
}